
package com.idealighter.game.games.happyfive;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

import com.idealighter.game.core.common.Game;
import com.idealighter.game.dictionary.dic.HappyFiveRobotRulesDic;
import com.idealighter.game.dictionary.domain.HappyFiveRobotRulesDomain;
import com.idealighter.game.dictionary.domain.HappyfiveRoomDomain;
import com.idealighter.game.dictionary.domain.RobotConfigDomain;
import com.idealighter.game.gamehall.dto.MemInfo;
import com.idealighter.game.gamehall.dto.SeatInfo;
import com.idealighter.game.games.happyfive.message.ReqBetDecisionMsg;
import com.idealighter.game.games.happyfive.message.ReqEnterGameHallMsg;
import com.idealighter.game.games.happyfive.message.ReqEnterRoomMsg;
import com.idealighter.game.games.happyfive.message.ReqEnterTableMsg;
import com.idealighter.game.robot.common.cards.Card;
import com.idealighter.game.robot.common.cards.Cards;
import com.idealighter.game.robot.common.cards.HappyFivePowerCompare;
import com.idealighter.game.robot.context.ApplicationContext;
import com.idealighter.game.robot.core.Player;
import com.idealighter.utils.code.RandCodeUtil;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.slf4j.LoggerFactory;

/**
 * 欢乐五张机器人 .
 * 
 * @author zsc .
 * @date 2016年3月24日 上午10:32:21
 *
 */
public class HappyFivePlayer extends Player {
  // 当前轮次下注的筹码数
  public long curBet = 0;
  // 每次的下注筹码数
  public List<Long> betRecord = Lists.newArrayList();
  // 下注类型 0:跟注，1：加注1，2：加注2，3：加注3, 4:梭哈，5：弃牌
  public int betType = 0;
  // 下注数量
  public long betAmount = 0;
  // 是否有人梭哈
  public boolean isAllIn = false;
  // 下注次数
  public int betCount = 1;
  // 是否加注过
  public boolean isRaise = false;
  // 是否有人看牌
  public boolean isLighCard = false;
  public HappyFiveRobotRulesDomain domain = new HappyFiveRobotRulesDomain();
  public Map<Integer, List<Integer>> othersCardList = Maps.newConcurrentMap();
  public List<Integer> cardList = Lists.newArrayList();
  private HappyFiveRobotRulesDic happyfiveRobotDic =
      ApplicationContext.getBean(HappyFiveRobotRulesDic.class);
  private HappyFivePowerCompare happyFivePowerCompare =
      ApplicationContext.getBean(HappyFivePowerCompare.class);
  private Cards happyFiveCard = ApplicationContext.getBean(Cards.class);

  public HappyfiveRoomDomain roomDomain;

  /**
   * 构造函数.
   * 
   * @param playerId .
   * @param userName .
   * @param roomId .
   * @param initGold .
   * @param totalGameNum .
   * @param tableGameNum .
   */
  public HappyFivePlayer(long playerId, String userName, int roomId, int initGold, int totalGameNum,
      int tableGameNum, RobotConfigDomain configDomain, HappyfiveRoomDomain roomDomain) {
    super(playerId, userName, roomId, initGold, totalGameNum, tableGameNum, configDomain);
    this.roomDomain = roomDomain;
  }

  /**
   * 机器人下注策略.
   *
   * @param maxBet .
   * @param allInBet .
   */
  public void betDesision(long maxBet, long allInBet) {
    final MemInfo memInfo = member(playerId);
    List<Card> cards = Lists.newArrayList();
    cards.addAll(cardList.stream()
        .map(card -> happyFiveCard.card(Card.cardSuit(card), Card.cardNumber(card)))
        .collect(Collectors.toList()));
    Map<Integer, List<Card>> other = Maps.newConcurrentMap();
    for (Map.Entry<Integer, List<Integer>> entry : othersCardList.entrySet()) {
      int key = entry.getKey();
      List<Integer> info = entry.getValue();
      List<Card> otherCards = Lists.newArrayList();
      otherCards.addAll(
          info.stream().map(card -> happyFiveCard.card(Card.cardSuit(card), Card.cardNumber(card)))
              .collect(Collectors.toList()));
      other.put(key, otherCards);
    }
    // betCount = betCount > 1 ? 1 : betCount;
    domain.setCardsNum(getSate());
    domain.setTimes(betCount);
    domain.setShowHandOthers(isAllIn ? 1 : 0);
    happyFivePowerCompare.isHave(cards, domain, other);
    betType = loadRobotRules();
    if (betType > 0 && betType <= 3 && isRaise) {
      /**
       * 强制更改下注 ->下注类型不对
       */
      betType = 0;
    }
    if (isAllIn && betType < 4) {
      betType = RandCodeUtil.randomBoolean() ? 4 : 5;
    }
    long betNum = betNum(maxBet, allInBet);
    if (betNum > memInfo.getChips()) {
      betType = 5;
      betNum = 0;
      System.err.println("异常弃牌");
    }
    betAmount = betNum;
    // betCount += 1;
  }

  /**
   * 下注 .
   */
  public void sendBetInfo() {
    ReqBetDecisionMsg msg = new ReqBetDecisionMsg();
    msg.setType(betType);
    msg.setBet(betAmount);
    betRecord.add(betAmount);
    sendMsg(msg);
    LOG.info("[欢乐五张][{}],下注了 ,类型[{}], 数量[{}]", playerInfo.getNickName(), betType,
        betAmount + curBet);
  }

  private int getSate() {
    int state = 1;
    switch (cardList.size()) {
      case 2:
        state = 1;
        break;
      case 3:
        state = 2;
        break;
      case 4:
        state = 3;
        break;
      case 5:
        state = 4;
        break;
      default:
        break;
    }
    return state;
  }

  /**
   * 下注数量计算.
   *
   * @param maxBet .
   * @param allInBet .
   * @return .
   */
  private long betNum(long maxBet, long allInBet) {
    if (betType == 0) { // call
      return maxBet - curBet;
    } else if (betType == 1) { // raise one
      return maxBet + roomDomain.getMinOne();
    } else if (betType == 2) { // raise two
      return maxBet + roomDomain.getMinOne() * 2;
    } else if (betType == 3) { // raise three
      return maxBet + roomDomain.getMinOne() * 3;
    } else if (betType == 4) {
      return allInBet; // allin
    } else {
      return 0; // fold
    }
  }

  /**
   * 机器人读表操作.
   *
   * @return .
   */
  private int loadRobotRules() {
    if (!happyfiveRobotDic.list().contains(domain)) {
      domain.toString();
      cardToString();
      domain.setTimeMin(happyfiveRobotDic.list().get(0).getTimeMin());
      domain.setTimeMax(happyfiveRobotDic.list().get(0).getTimeMax());
      return randHand(happyfiveRobotDic.list().get(0));
    } else {
      for (HappyFiveRobotRulesDomain domains : happyfiveRobotDic.list()) {
        if (domains.equals(domain)) {
          domain.setTimeMin(domains.getTimeMin());
          domain.setTimeMax(domains.getTimeMax());
          return randHand(domains);
        }
      }
    }
    return 5;
  }

  /**
   * 根据概率随机一种操作.
   *
   * @param domain .
   * @return .
   */
  private int randHand(HappyFiveRobotRulesDomain domain) {
    int rand = RandCodeUtil.random(10000);
    if (rand <= domain.getFollow()) {
      return 0;
    }
    if (rand <= domain.getFollow() + domain.getFilling1()) {
      return 1;
    }
    if (rand <= domain.getFollow() + domain.getFilling2() + domain.getFilling1()) {
      return 2;
    }
    if (rand <= domain.getFollow() + domain.getFilling2() + domain.getFilling1()
        + domain.getFilling3()) {
      return 3;
    }
    if (rand <= domain.getFollow() + domain.getFilling2() + domain.getFilling1()
        + domain.getFilling3() + domain.getShowhand()) {
      return 4;
    }
    return 5;
  }

  /**
   * 充值数据 .
   */
  public void resetData() {
    domain = new HappyFiveRobotRulesDomain();
    cardList.clear();
    betRecord.clear();
    othersCardList.clear();
    curBet = 0;
    isAllIn = false;
    isRaise = false;
    isLighCard = false;
  }

  @Override
  public boolean goldCheck() {
    long gold = playerInfo.getGold();
    if (gold < roomDomain.getLower()) {
      LOG.info("[欢乐五张]机器人[{}][{}]金币小于房间下限退出游戏", userName, playerId);
      delayLogout();
      return false;
    }

    if (gold > roomDomain.getUpper()) {
      LOG.info("[欢乐五张]机器人[{}][{}]金币高于房间下限退出游戏", userName, playerId);
      delayLogout();
      return false;
    }

    if (gold < roomDomain.getAfee()) {
      LOG.info("[欢乐五张]机器人[{}][{}]金币小于台费退出游戏", userName, playerId);
      delayLogout();
      return false;
    }
    return true;
  }

  @Override
  public void enterGameHall() {
    sendMsg(new ReqEnterGameHallMsg());
  }

  @Override
  public void enterRoom() {
    if (rooms.contains(roomId)) {
      if (!goldCheck()) {
        return;
      }
      ReqEnterRoomMsg msg = new ReqEnterRoomMsg();
      msg.setRoomId(roomId);
      sendMsg(msg);
    }
  }

  @Override
  public void enterTable() {
    if (!goldCheck()) {
      return;
    }
    SeatInfo emptySeat = findNoGamingEmptySeat();
    if (emptySeat != null) {
      ReqEnterTableMsg msg = new ReqEnterTableMsg();
      msg.setTableId((int) emptySeat.getTableId());
      msg.setOrder((byte) emptySeat.getOrder());
      msg.setPassword("");
      sendMsg(msg);
    }
  }

  @Override
  public Game game() {
    return Game.HAPPY_FIVE;
  }

  @Override
  public boolean enterPwdTableAble() {
    return false;
  }

  private void cardToString() {
    String handcardmsg = "";
    List<Card> cards = Lists.newArrayList();
    cards.addAll(cardList.stream()
        .map(card -> happyFiveCard.card(Card.cardSuit(card), Card.cardNumber(card)))
        .collect(Collectors.toList()));
    /**
     * 手牌
     */
    for (Card cardString : cards) {
      handcardmsg += cardString.toString();
    }
    String msg = "手牌:" + handcardmsg;
    LoggerFactory.getLogger("HappyFiveRuleLog").info(msg);

  }

}
